local ROT = require 'rot'
local RNG = ROT.RNG

local Scene = require 'game.scene'

local SceneSpec = Scene:extend()

SceneSpec.name = 'Wallhenge'

SceneSpec.innerWidth = 42
SceneSpec.innerHeight = 42
SceneSpec.maxDepth = 7
SceneSpec.outdoors = true

function SceneSpec:build(depth, x1, y1, x2, y2)

    local m

    if depth == 1 then
        self.innerWidth = 36
        self.innerHeight = 36
    end

    if depth > 0 then
        self.name = 'Wallhenge ' .. tostring(depth)
        m = ROT.Map.Uniform:new(self.innerWidth, self.innerHeight, {
            roomDugPercentage = 0.4,
            roomWidth = { 7, 8 },
            roomHeight = { 7, 8 },
        })
        m:create(function (x, y, val)
            self.feature:setCell(x, y, val == 0 and 'xfloor' or nil)
        end)

        local rooms = m:getRooms()
        local i = #rooms
        if i >= 7 then
            local r = rooms[7]
            require 'scene.hell' .build(self, 0,
                r:getLeft(), r:getTop(), r:getRight(), r:getBottom())
        end

        self:expand('grass')
        self:expand('tree')
    else
        local x, y = math.floor((x1 + x2) * 0.5), math.floor((y1 + y2) * 0.5)

        for _x = x1, x2 do for _y = y1, y2 do
            self.feature:setCell(_x, _y, 'tree')
        end end

        self.feature:setCell(x, y, 'grass')

        self.branches[#self.branches + 1] = { x = x, y = y, branch = 'forest' }
        self.feature:setCell(x, y, 'downstairs')

        self:decimate('tree', 7, 1, 'grass')
    end

    for i = 1, 4 do
        self:decimate('tree', 3, 1, 'grass')
        self:decimate('tree', 5, 1, 'grass')
    end

    if depth < 1 then
        return
    end

    self:decimate('xfloor', 8, 1, 'xwall')

    self:decimate('xwall', 3, 1, 'xfloor')
    self:decimate('xwall', 8, 1, 'dirt floor', function(_, x, y)
        self.player.x, self.player.y = x, y
    end)
    self:decimate('xwall', 3, 1, 'xfloor')

    for i, x, y, v in self.feature:each() do
       if v == 'xwall' then self.feature:setCell(x, y, 'wall') end
       if v == 'xfloor' then self.feature:setCell(x, y, 'grass') end
    end

    self:expand('tree')

    for i = 1, 3 do
        self:decimate('tree', 3, 1, 'grass')
        self:decimate('tree', 5, 1, 'grass', function(self, x, y)

                if RNG:random() <= 0.25 then
                    self:putItem(x, y, 'stick')
                end
                if RNG:random() <= 0.05 then
                    local mob = self:spawn(x, y, 'boar')
                elseif RNG:random() <= 0.05 then
                    local mob = self:spawn(x, y, 'snake')
                end
            end)
    end

    self:expand('tree')
    self:expand('tree')
    self:expand('sand')
    self:expand('tree')

    for i = 1, 2 do
        self:expand('shallow water')
        self:fabricate('sand', 3, 1)
    end

    self:expand('deep water')

    self:decimate('grass', 8, 1, 'rose')

    for i = 1, 8 do
        self:decimate('rose', 5, 1, 'xtree')
        self:decimate('rose', 1, 1, 'xtree')
        self:decimate('rose', 3, 1, 'xtree')
    end

    self:decimate('rose', 2, 1, 'grass')
    self:decimate('xtree', 4, 1, 'tall grass')
    self:decimate('xtree', 3, 1, 'tall grass')

    self:decimate('tree', 2, 1, 'grass')
    self:decimate('tree', 1, 1, 'tall grass')

    for i = 1, 4 do
        self:decimate('tree', 5, 1, 'tall grass')
    end

    for i, x, y, v in self.feature:each() do
       if v == 'xtree' then self.feature:setCell(x, y, 'tree') end
    end

    self:with('grass'):near('tree', 1):near('tall grass', 1):swap('shrooms'):apply()

    local rooms = m:getRooms()
    local offset = depth == 1 and 1 or #self.previous.downstairs

    for i = 1, offset do
        local c = rooms[i]:getCenter()
        local x, y = c[1], c[2]
        self.upstairs[i] = { x = x, y = y }
        self.feature:setCell(x, y, 'upstairs')
        self.player.x, self.player.y = x, y
    end

    if depth < self.maxDepth then
        for i = offset + 1, offset + 3 do
            if not rooms[i] then break end
            local c = rooms[i]:getCenter()
            local x, y = c[1], c[2]
            self.downstairs[i - offset] = { x = x, y = y }
            self.feature:setCell(x, y, 'downstairs')
        end
    end
end

return SceneSpec
